﻿using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;

namespace SHomeWorkshop.LunarPresentation.Adorners
{
    public class IndentAdorner : Adorner
    {
        // Be sure to call the base class constructor.
        /// <summary>
        /// 用以表示缩进状态的装饰器。
        /// </summary>
        /// <param name="adornedElement">应传入公式的“MainBorder”主子元素。</param>
        /// <param name="masterExpression">宿主公式，装饰器就是表示这个公式的被选取状态。</param>
        public IndentAdorner(UIElement adornedElement, Expressions.Expression masterExpression)
            : base(adornedElement)
        {
            this.masterExpression = masterExpression;

            //终于解决了选取装饰器中线条宽度为2而不是1像素的问题！！！
            this.SnapsToDevicePixels = true;
            this.SetValue(RenderOptions.EdgeModeProperty, EdgeMode.Aliased);

            Cursor = System.Windows.Input.Cursors.Hand;
            MouseLeftButtonDown += new System.Windows.Input.MouseButtonEventHandler(IndentAdorner_MouseLeftButtonDown);
            MouseLeftButtonUp += new System.Windows.Input.MouseButtonEventHandler(IndentAdorner_MouseLeftButtonUp);

            MouseRightButtonDown += new MouseButtonEventHandler(IndentAdorner_MouseRightButtonDown);

            MouseEnter += new System.Windows.Input.MouseEventHandler(IndentAdorner_MouseEnter);
            MouseLeave += new System.Windows.Input.MouseEventHandler(IndentAdorner_MouseLeave);
        }

        void IndentAdorner_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (masterExpression != null && masterExpression.Editor != null)
            {
                if (masterExpression.Editor.SelectedExpression != masterExpression)
                {
                    masterExpression.Editor.SelectedExpression = masterExpression;
                }
            }

            e.Handled = true;
        }

        void IndentAdorner_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            //完成拖动。
            Globals.DropExpression(this.masterExpression);
        }

        void IndentAdorner_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
        {
            InvalidateVisual();
        }

        void IndentAdorner_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)
        {
            InvalidateVisual();
        }

        void IndentAdorner_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            if (masterExpression != null && masterExpression.Editor != null)
            {
                if (masterExpression.Editor.SelectedExpression != masterExpression)
                {
                    masterExpression.Editor.SelectedExpression = masterExpression;
                }

                if (Globals.dragSourceExpression != masterExpression)
                {
                    Globals.dragSourceExpression = masterExpression;
                }
            }
            e.Handled = true;
        }

        private Expressions.Expression masterExpression;

        public Expressions.Expression MasterExpression
        {
            get { return masterExpression; }
        }

        // A common way to implement an adorner's rendering behavior is to override the OnRender
        // method, which is called by the layout system as part of a rendering pass.
        protected override void OnRender(DrawingContext drawingContext)
        {
            if (masterExpression is Expressions.SubPanel) return;//子面板不缩进，没有必要画缩进层级的序号。
            if (masterExpression.ParentPanel == null ||
                masterExpression.ParentPanel.Direction != Orientation.Vertical) return;//父子面板水平对齐，不画缩进层级序号。

            if (masterExpression.Indent <= 0) return;//普通公式在缩进为零时，是没有空间绘制缩进层级的序号的。

            Rect adornedElementRect = new Rect(this.AdornedElement.RenderSize);

            double width = masterExpression.Editor.ExFontSize;

            if (masterExpression is Expressions.BaseText)
            {
                Expressions.BaseText bt = masterExpression as Expressions.BaseText;
                if (bt.TaskItemType == Expressions.BaseText.TaskType.NotTask)
                {
                    Draw(drawingContext, adornedElementRect, width);
                    return;
                }

                DrawTaskItemBox(drawingContext, bt, adornedElementRect, width);
            }
            else
            {
                Draw(drawingContext, adornedElementRect, width);
            }
        }

        private void DrawTaskItemBox(DrawingContext drawingContext,
            Expressions.BaseText bt, Rect adornedElementRect, double width)
        {
            if (bt.ParentPanel == null) return;
            if (bt.ParentPanel.BasePanel.Orientation == Orientation.Horizontal) return;

            if (bt.Indent <= 0) return;

            if (bt.Indent > 0)
            {
                string str = "";
                if (bt.TaskItemType != Expressions.BaseText.TaskType.NotTask)
                {
                    string taskName = "";
                    switch (bt.TaskItemType)
                    {
                        case Expressions.BaseText.TaskType.Aborted:
                            {
                                taskName = "任务：已失败"; break;
                            }
                        case Expressions.BaseText.TaskType.Finished:
                            {
                                taskName = "任务：已完成"; break;
                            }
                        case Expressions.BaseText.TaskType.NotStarted:
                            {
                                taskName = "任务：在准备"; break;
                            }
                        case Expressions.BaseText.TaskType.Paused:
                            {
                                taskName = "任务：已暂停"; break;
                            }
                        case Expressions.BaseText.TaskType.Running:
                            {
                                taskName = "任务：在运行"; break;
                            }
                    }
                    str += taskName + (taskName.Length > 0 ? "\r\n============\r\n" : "");
                }

                if (bt.IsHeaderText && bt.Indent <= 3)
                {

                    str += "标题：" + (bt.Indent + 1).ToString() + "级\r\n============\r\n<" + bt.ChineseName + ">";
                }
                else
                {
                    str += "左缩进：" + bt.Indent.ToString() + "\r\n============\r\n<" + bt.ChineseName + ">";
                }

                ToolTip = str;
            }
            else
            {
                ToolTip = null;
            }

            Rect rect = new Rect(adornedElementRect.Left - width - 4,
                (adornedElementRect.Height - width) / 2, width, width);

            Rect backRect = new Rect(adornedElementRect.Left - width - 4, adornedElementRect.Top,
                width, adornedElementRect.Height);

            Brush renderBrush = bt.ExForeground;
            Pen renderPen = new Pen(bt.ExForeground, 1);

            drawingContext.DrawRectangle(Brushes.Transparent, renderPen, rect);

            switch (bt.TaskItemType)
            {
                case Expressions.BaseText.TaskType.Aborted:
                    {
                        drawingContext.DrawLine(renderPen,
                            new Point(rect.Left + 2, rect.Top + 2),
                            new Point(rect.Right - 3, rect.Bottom - 3));
                        drawingContext.DrawLine(renderPen,
                            new Point(rect.Right - 3, rect.Top + 2),
                            new Point(rect.Left + 2, rect.Bottom - 3));
                        break;
                    }
                case Expressions.BaseText.TaskType.Finished:
                    {
                        drawingContext.DrawRectangle(renderBrush, renderPen,
                            new Rect(new Point(rect.Left + 2, rect.Top + 2),
                                new Size(rect.Width - 4, rect.Height - 4)));
                        break;
                    }
                //case Expressions.BaseText.TaskType.NotStarted://已绘制空框。
                //case Expressions.BaseText.TaskType.NotTask://已返回。
                case Expressions.BaseText.TaskType.Paused:
                    {
                        drawingContext.DrawRectangle(renderBrush, renderPen,
                            new Rect(new Point(rect.Left + 3, rect.Top + 2),
                                new Size((rect.Width - 4) / 2 - 2, rect.Height - 4)));
                        drawingContext.DrawRectangle(renderBrush, renderPen,
                            new Rect(new Point(rect.Left + 2 + (rect.Width - 4) / 2 + 1, rect.Top + 2),
                                new Size((rect.Width - 4) / 2 - 2, rect.Height - 4)));
                        break;
                    }
                case Expressions.BaseText.TaskType.Running:
                    {
                        renderPen.EndLineCap = PenLineCap.Square;

                        Point ptLT = new Point(rect.Left + 2, rect.Top + 2);
                        Point ptRT = new Point(rect.Right - 3, rect.Top + 2);
                        Point ptLB = new Point(rect.Left + 2, rect.Bottom - 3);

                        PathGeometry pathGeometry = new PathGeometry();
                        PathFigure pf = new PathFigure() { StartPoint = ptLT };
                        PolyLineSegment pls = new PolyLineSegment(
                            new List<Point>() { ptRT, ptLB, ptLT }, true);
                        pf.Segments.Add(pls);
                        pathGeometry.Figures.Add(pf);

                        drawingContext.DrawGeometry(renderBrush, renderPen, pathGeometry);

                        break;
                    }
            }
        }

        private void Draw(DrawingContext drawingContext, Rect adornedElementRect, double width)
        {
            #region 绘制装饰器。
            //Brush handleBrush;
            Pen commentPen;
            if (IsMouseOver)
            {
                if (this.masterExpression != null &&
                    this.masterExpression.Editor != null)
                {
                    commentPen = new Pen(this.masterExpression.Editor.DefaultForeground, 1);
                    //handleBrush = Globals.expressionIndentHandleBrush;
                }
                else
                {
                    commentPen = new Pen(Brushes.White, 1);
                }
            }
            else
            {
                commentPen = new Pen(Brushes.Transparent, 1);//鼠标不在也是绘制，否则就无法在鼠标移进时察看了。
                //handleBrush = Brushes.Transparent;
            }

            Rect baseRect = new Rect(adornedElementRect.Left - width - 4,
                    (adornedElementRect.Height - width) / 2, width, width);

            Rect backRect = new Rect(adornedElementRect.Left - width - 4, adornedElementRect.Top,
                width, adornedElementRect.Height);
            Pen backPen = new Pen(Brushes.Transparent, 1);

            double hw = width / 2;
            double tw = width / 3;
            double qw = width / 4;
            drawingContext.DrawRectangle(/*commentBrush*/Brushes.Transparent, backPen, backRect);

            #region 画线代码，已废弃。
            //PathGeometry geometry = new PathGeometry();
            //PathFigure pathFigure = new PathFigure();
            //pathFigure.IsClosed = false;
            //Point rightTop = new Point(adornedElementRect.TopLeft.X - 2, adornedElementRect.TopLeft.Y);//半圆弧形右上角。
            //Point leftTop = new Point(adornedElementRect.TopLeft.X - width / 4 - 2, adornedElementRect.TopLeft.Y);
            //Point leftBottom = new Point(adornedElementRect.BottomLeft.X - width / 4 - 2, adornedElementRect.BottomLeft.Y);
            //Point rightBottom = new Point(adornedElementRect.BottomLeft.X - 2, adornedElementRect.BottomLeft.Y);

            //pathFigure.StartPoint = rightTop;
            //Point b1Start = new Point(rightTop.X - width / 8, rightTop.Y);
            //Point b1End = new Point(leftTop.X, leftTop.Y + width / 8);
            //LineSegment ls1 = new LineSegment(b1Start, false);//从右顶点向左的短横线。
            //LineSegment lsTop = new LineSegment(b1End, false);//上斜线
            //Point b2Start = new Point(leftBottom.X, leftBottom.Y - width / 8);
            //LineSegment ls2 = new LineSegment(b2Start, false);//两个斜线间的短竖线（左）
            //Point b2End = new Point(leftBottom.X + width / 8, leftBottom.Y);
            //LineSegment lsBottom = new LineSegment(b2End, false);//下斜线
            //LineSegment ls3 = new LineSegment(rightBottom, false);
            //LineSegment ls4 = new LineSegment(rightTop, false);//右竖线，收尾。

            //Point l1End = new Point(leftTop.X, leftTop.Y + width / 4);
            //LineSegment ls1 = new LineSegment(l1End, false);
            //Point l2End = new Point(leftBottom.X, leftBottom.Y - width / 4);
            //LineSegment ls2 = new LineSegment(l2End, false);
            //LineSegment ls3 = new LineSegment(rightBottom, false);

            //pathFigure.Segments.Add(ls1);
            ////pathFigure.Segments.Add(lsTop);
            //pathFigure.Segments.Add(ls2);
            ////pathFigure.Segments.Add(lsBottom);
            //pathFigure.Segments.Add(ls3);
            ////pathFigure.Segments.Add(ls4);
            //geometry.Figures.Add(pathFigure);
            //GeometryDrawing gd = new GeometryDrawing(handleBrush, commentPen, geometry);

            //drawingContext.DrawDrawing(gd);
            #endregion

            if (masterExpression.Indent > 0)
            {
                if (masterExpression is Expressions.BaseText &&
                    (masterExpression as Expressions.BaseText).IsHeaderText &&
                    masterExpression.Indent <= 3)
                {
                    ToolTip = "标题：" + (masterExpression.Indent + 1).ToString() + "级\r\n=========\r\n<" + masterExpression.ChineseName + ">";
                }
                else
                {
                    ToolTip = "左缩进：" + masterExpression.Indent.ToString() + "\r\n=========\r\n<" + masterExpression.ChineseName + ">";
                }

                drawingContext.DrawRectangle(Brushes.Transparent, commentPen, baseRect);

                drawingContext.DrawLine(commentPen, backRect.TopRight, backRect.BottomRight);
            }
            else
            {
                ToolTip = null;
            }

            #region 原版的缩进标记，带层级标志。
            switch (masterExpression.Indent)
            {
                case 1:
                    {
                        drawingContext.DrawLine(commentPen, new Point(baseRect.Left, baseRect.TopLeft.Y + hw),
                            new Point(baseRect.Right, baseRect.TopLeft.Y + hw));
                        break;
                    }
                case 2:
                    {
                        drawingContext.DrawLine(commentPen, new Point(baseRect.Left, baseRect.TopLeft.Y + tw),
                            new Point(baseRect.Right, baseRect.TopLeft.Y + tw));
                        drawingContext.DrawLine(commentPen, new Point(baseRect.Left, baseRect.TopLeft.Y + tw * 2),
                            new Point(baseRect.Right, baseRect.TopLeft.Y + tw * 2));
                        break;
                    }
                case 3:
                    {
                        drawingContext.DrawLine(commentPen, new Point(baseRect.Left, baseRect.TopLeft.Y + qw),
                            new Point(baseRect.Right, baseRect.TopLeft.Y + qw));
                        drawingContext.DrawLine(commentPen, new Point(baseRect.Left, baseRect.TopLeft.Y + hw),
                            new Point(baseRect.Right, baseRect.TopLeft.Y + hw));
                        drawingContext.DrawLine(commentPen, new Point(baseRect.Left, baseRect.TopLeft.Y + qw * 3),
                            new Point(baseRect.Right, baseRect.TopLeft.Y + qw * 3));
                        break;
                    }
                case 4:
                    {
                        Point lt = new Point(baseRect.Left, baseRect.TopLeft.Y + qw);//左上
                        Point rb = new Point(baseRect.Right, baseRect.BottomRight.Y - qw);//右下
                        Point rt = new Point(rb.X, lt.Y);
                        Point lb = new Point(lt.X, rb.Y);
                        drawingContext.DrawLine(commentPen, lt, rt);//顶横线
                        //drawingContext.DrawLine(commentPen, rt, rb);//右竖线
                        drawingContext.DrawLine(commentPen, rb, lb);//底横线
                        //drawingContext.DrawLine(commentPen, lb, lt);//左竖线

                        Point lmt = new Point(lt.X + (rt.X - lt.X) / 3, lt.Y);
                        Point rmt = new Point(lt.X + (rt.X - lt.X) * 2 / 3, lt.Y);
                        Point lmb = new Point(lmt.X, lb.Y);
                        Point rmb = new Point(rmt.X, lb.Y);
                        drawingContext.DrawLine(commentPen, lmt, lmb);
                        drawingContext.DrawLine(commentPen, rmt, rmb);
                        break;
                    }
                case 5:
                    {
                        Point lt = new Point(baseRect.Left, baseRect.TopLeft.Y + qw);//左上
                        Point rb = new Point(baseRect.Right, baseRect.BottomRight.Y - qw);//右下
                        Point lm = new Point(lt.X + (rb.X - lt.X) / 4, lt.Y + (rb.Y - lt.Y) / 2);//左中
                        Point rm = new Point(rb.X - (rb.X - lt.X) / 4, lm.Y);//右中
                        drawingContext.DrawLine(commentPen, lt, new Point(rb.X, lt.Y));//顶横线
                        drawingContext.DrawLine(commentPen, lm, rm);//中横线
                        drawingContext.DrawLine(commentPen, new Point(lm.X, lt.Y), lm);//左竖线
                        drawingContext.DrawLine(commentPen, new Point(lt.X + (rb.X - lt.X) / 2, lt.Y), new Point(lt.X + (rb.X - lt.X) / 2, rb.Y));//中竖线
                        drawingContext.DrawLine(commentPen, rm, new Point(rm.X, rb.Y));//右竖线
                        drawingContext.DrawLine(commentPen, new Point(lt.X, rb.Y), rb); //底横线
                        break;
                    }
                case 6:
                    {
                        Point lt = baseRect.TopLeft;//左上
                        Point rb = baseRect.BottomRight;//右下
                        Point lm = new Point(baseRect.Left, (baseRect.BottomRight.Y - baseRect.TopLeft.Y) / 2 + baseRect.TopLeft.Y);//左中
                        Point rm = new Point(baseRect.Right, lm.Y);//右中
                        Point rt = new Point(rb.X, lt.Y);
                        Point lb = new Point(lt.X, rb.Y);
                        drawingContext.DrawLine(commentPen, new Point(lt.X + (rb.X - lt.X) / 2, lt.Y),
                            new Point(lt.X + (rb.X - lt.X) / 2, lt.Y + (rb.Y - lt.Y) / 2));//顶竖线
                        drawingContext.DrawLine(commentPen, lm, rm);//中横线

                        Point lmt = new Point(lt.X + (rt.X - lt.X) / 3, lm.Y);
                        Point rmt = new Point(lt.X + (rt.X - lt.X) * 2 / 3, lm.Y);
                        Point lmb = new Point(lmt.X, lb.Y);
                        Point rmb = new Point(rmt.X, lb.Y);
                        drawingContext.DrawLine(commentPen, lmt, lmb);
                        drawingContext.DrawLine(commentPen, rmt, rmb);
                        break;
                    }
            }
            #endregion
            #endregion
        }
    }
}